package com.brillilab.service.core.lab.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.brillilab.common.utils.CodeUtil;
import com.brillilab.common.utils.DateUtil;
import com.brillilab.dao.mapper.lab.LabMapper;
import com.brillilab.domain.enums.lab.LabEnum;
import com.brillilab.domain.enums.lab.UserEnum;
import com.brillilab.domain.po.lab.Lab;
import com.brillilab.domain.po.lab.LabExpireJob;
import com.brillilab.domain.po.lab.LabMember;
import com.brillilab.domain.po.user.Users;
import com.brillilab.service.constant.JobConstants;
import com.brillilab.service.core.lab.ILabExpireJobService;
import com.brillilab.service.core.lab.ILabMemberService;
import com.brillilab.service.core.lab.ILabService;
import com.brillilab.service.core.user.IInviteCodeService;
import com.brillilab.service.core.user.IUsersService;
import com.brillilab.service.job.lab.BeforeLabExpireJob;
import com.brillilab.service.job.lab.WhenLabExpireJob;
import com.brillilab.service.logic.message.MessageLogic;
import com.brillilab.service.module.aliyun.AliYunSms;
import com.brillilab.service.quartz.BrillQuartzScheduler;
import com.brillilab.service.utils.QuartzUtils;
import org.quartz.JobDataMap;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
@Transactional
public class LabServiceImpl implements ILabService {
    @Resource
    private LabMapper labMapper;
    @Resource
    private BrillQuartzScheduler scheduler;
    @Resource
    private ILabExpireJobService labExpireJobService;
    @Resource
    private IInviteCodeService inviteCodeService;
    @Resource
    private ILabMemberService labMemberService;
    @Resource
    private IUsersService usersService;
    @Resource
    private MessageLogic messageLogic;
    @Resource
    private AliYunSms aliYunSms;

    public Lab insert(Lab lab) {
        int b = labMapper.insert(lab);
        Assert.isTrue(b == 1, "添加失败");
        return lab;
    }

    public boolean updateById(Lab lab) {
        int b = labMapper.updateById(lab);
        return b == 1 ? true : false;
    }

    public boolean updateState(Long id, Integer state) {
        Assert.isTrue(LabEnum.State.getKey(state) != null, "参数错误");
        Lab lab = labMapper.selectById(id);
        lab.setState(state);
        int b = labMapper.updateById(lab);
        return b == 1 ? true : false;
    }

    public Lab selectById(Long id) {
        return labMapper.selectById(id);
    }

    @Override
    public Lab selectByOwnerId(Long ownerId) {
        LambdaQueryWrapper<Lab> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Lab::getOwnerId, ownerId);
        List<Lab> labList = labMapper.selectList(wrapper);
        return CollectionUtils.isEmpty(labList) == false ? labList.get(0) : null;
    }

    @Override
    public Lab selectByLabNameAndOrgName(String labName, String orgName, String academy) {
        LambdaQueryWrapper<Lab> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Lab::getName, labName);
        wrapper.eq(Lab::getOrgName, orgName);
        wrapper.eq(Lab::getAcademy, academy);
        return labMapper.selectOne(wrapper);
    }

    @Override
    public Lab selectByLabNameAndOrgInfo(String labName, Long orgId, String academy) {
        LambdaQueryWrapper<Lab> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Lab::getName, labName);
        wrapper.eq(Lab::getOrgId, orgId);
        wrapper.eq(Lab::getAcademy, academy);
        return labMapper.selectOne(wrapper);
    }

    @Override
    public List<Lab> selectListByIdList(List<Long> labIdList) {
        LambdaQueryWrapper<Lab> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(Lab::getId, labIdList);
        return labMapper.selectList(wrapper);
    }

    @Override
    public List<Lab> selectList(Long orgId) {
        LambdaQueryWrapper<Lab> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Lab::getOrgId, orgId);
        return labMapper.selectList(wrapper);
    }

    /**
     * 试用实验室过期定时任务
     *
     * @param lab
     * @return
     */
    @Override
    public boolean createLabExpireJobs(Lab lab) {

        Assert.notNull(lab, "实验室不存在!");
        Assert.isTrue(lab.getOwnerId() != null, "实验室无PI!");
        Users users = usersService.selectUser(lab.getOwnerId(), UserEnum.State.NORMAL.getValue());
        Assert.notNull(users, "PI不存在!");
        LabMember labMember = labMemberService.selectMember(lab.getId(), lab.getOwnerId());
        Assert.notNull(labMember, "PI不存在!");

        JobDataMap jobDataMap = new JobDataMap();
        jobDataMap.put("labId", lab.getId());
        jobDataMap.put("ownerId", lab.getOwnerId());
        jobDataMap.put("labMemberId", labMember.getId());
        jobDataMap.put("mobile", users.getMobile());
        jobDataMap.put("labName", lab.getName());
        jobDataMap.put("userName", users.getName());

        //定时提醒时间调整为上午10点
        String dateString = DateUtil.dateString(lab.getExpireDate(), "yyyy-MM-dd 10:00:00");
        Date expireDate = DateUtil.stringToDate(dateString, "yyyy-MM-dd HH:mm:ss");
        long expireTime = expireDate.getTime();

        Date sevenDay = new Date(expireTime - 7 * 24 * 3600 * 1000L);
        Date threeDay = new Date(expireTime - 3 * 24 * 3600 * 1000L);
        Date oneDay = new Date(expireTime - 24 * 3600 * 1000L);
        Date zeroDay = new Date(expireTime - 24 * 3600 * 1000L);

        String sevenDayId = JobConstants.JOB_GROUP_LAB_EXPIRE + CodeUtil.getUUID();
        String threeDayId = JobConstants.JOB_GROUP_LAB_EXPIRE + CodeUtil.getUUID();
        String oneDayId = JobConstants.JOB_GROUP_LAB_EXPIRE + CodeUtil.getUUID();
        String endDayId = JobConstants.JOB_GROUP_LAB_EXPIRE + CodeUtil.getUUID();

        //7天
        jobDataMap.put("days", 7);
        scheduler.createJob(BeforeLabExpireJob.class, sevenDayId, JobConstants.JOB_GROUP_LAB_EXPIRE, QuartzUtils.getCronExpr(sevenDay), jobDataMap);
        //3天
        jobDataMap.put("days", 3);
        scheduler.createJob(BeforeLabExpireJob.class, threeDayId, JobConstants.JOB_GROUP_LAB_EXPIRE, QuartzUtils.getCronExpr(threeDay), jobDataMap);
        //1天
        jobDataMap.put("days", 1);
        scheduler.createJob(BeforeLabExpireJob.class, oneDayId, JobConstants.JOB_GROUP_LAB_EXPIRE, QuartzUtils.getCronExpr(oneDay), jobDataMap);
        //1天
        jobDataMap.put("days", 0);
        scheduler.createJob(WhenLabExpireJob.class, endDayId, JobConstants.JOB_GROUP_LAB_EXPIRE, QuartzUtils.getCronExpr(zeroDay), jobDataMap);

        List<LabExpireJob> labExpireJobs = new ArrayList<>();
        for (int i = 0; i < 4; i++) {
            LabExpireJob labExpireJob = new LabExpireJob();
            labExpireJob.setLabId(lab.getId());
            switch (i) {
                case 0:
                    labExpireJob.setJobName(sevenDayId);break;
                case 1:
                    labExpireJob.setJobName(threeDayId);break;
                case 2:
                    labExpireJob.setJobName(oneDayId);break;
                case 3:
                    labExpireJob.setJobName(endDayId);break;
                default:
            }
            labExpireJob.setJobGroup(JobConstants.JOB_GROUP_LAB_EXPIRE);
            labExpireJobs.add(labExpireJob);
        }

        return labExpireJobService.insertBatch(labExpireJobs) > 0;
    }

    @Override
    public List<Lab> selectAllLabList() {
        LambdaQueryWrapper<Lab> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(Lab::getState, 1);
        return labMapper.selectList(wrapper);
    }
}
